﻿namespace MefContrib.Models.Provider.Validation
{
    using System;
    using System.Diagnostics;
    using MefContrib.Models.Provider.Resources;

    /// <summary>
    /// 
    /// </summary>
    public static class ValidatorOfTExtensions
    {
        /// <summary>
        /// Ensures that the validated object is of a desired type.
        /// </summary>
        /// <typeparam name="T">The type of the argument which is being validated.</typeparam>
        /// <param name="target">A reference to the object which is being validated.</param>
        /// <param name="desiredType">The <see cref="Type"/> to ensure that the object is of.</param>
        /// <exception cref="InvalidCastException">The target was not of the type specified by the <paramref name="desiredType"/> parameter.</exception>
        //[DebuggerHidden]
        public static Validator<T> IsOfType<T>(this Validator<T> target, Type desiredType)
        {
            if (target.Value.GetType() != desiredType)
            {
                throw new InvalidCastException(ValidationErrors.IsOfType.FormatInvariant(target.Name, desiredType.FullName));
            }

            return target;
        }
        
        /// <summary>
        /// Ensures that a string is not empty.
        /// </summary>
        /// <param name="target">A reference to the object which is being validated.</param>
        /// <returns>A <see cref="Validator{T}"/> object.</returns>
        /// <exception cref="ArgumentException">The lenght of the target string was zero.</exception>
        [DebuggerHidden]
        public static Validator<string> NotEmpty(this Validator<string> target)
        {
            if (target.Value.Length == 0)
            {
                throw new ArgumentException(ValidationErrors.NotEmpty.FormatInvariant(target.Name));
            }

            return target;
        }

        /// <summary>
        /// Ensures that a reference type is not null.
        /// </summary>
        /// <typeparam name="T">The type of the argument which is being validated.</typeparam>
        /// <param name="target">A reference to the object which is being validated.</param>
        /// <returns>A <see cref="Validator{T}"/> object.</returns>
        /// <exception cref="ArgumentNullException">The value of the target object was null.</exception>
        [DebuggerHidden]
        public static Validator<T> NotNull<T>(this Validator<T> target) where T : class
        {
            if (target.Value == null)
            {
                throw new ArgumentNullException(ValidationErrors.NotNull.FormatInvariant(target.Name));
            }

            return target;
        }
    }
}